/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "Decode.h"
#include "DecodeNative.h"
#include "av_codec_sample_log.h"
#include "dfx/error/av_codec_sample_error.h"


#undef LOG_TAG
#define LOG_TAG "audio_waveform_decoder"

namespace {
using namespace std::chrono_literals;
} // namespace

Decode::~Decode() {
    // 如果还没有释放，触发释放流程
    if (!isReleased_) {
        // 标记为正在释放，避免在StopDecode中再次调用StartRelease
        isReleased_ = true;
        
        // 确保线程能够退出
        isStarted_ = false;
        isAudioDone_ = true;
        
        // 通知所有线程
        doneCond_.notify_all();
        
        // 简单地重置线程，而不是调用join，避免可能的死锁
        if (audioDecInputThread_) {
            audioDecInputThread_.reset();
        }
        if (audioDecOutputThread_) {
            audioDecOutputThread_.reset();
        }
        
        // 释放其他资源
        if (demuxer_) {
            demuxer_->Release();
            demuxer_.reset();
        }
        
        if (audioDecoder_) {
            audioDecoder_->Release();
            audioDecoder_.reset();
        }
        
        if (audioDecContext_) {
            delete audioDecContext_;
            audioDecContext_ = nullptr;
        }
        
        builder_ = nullptr;
        audioRenderer_ = nullptr;
    }
}

int32_t Decode::CreateAudioDecoder() {
    AVCODEC_SAMPLE_LOGW("audio mime:%{public}s", sampleInfo_.audioCodecMime.c_str());
    int32_t ret = audioDecoder_->Create(sampleInfo_.audioCodecMime);
    if (ret != AVCODEC_SAMPLE_ERR_OK) {
        AVCODEC_SAMPLE_LOGE("Create audio decoder failed, mime:%{public}s", sampleInfo_.audioCodecMime.c_str());
        return ret;
    }

    // 创建CodecUserData但不使用其中的renderQueue和renderCond
    audioDecContext_ = new CodecUserData;
    audioDecContext_->sampleInfo = &sampleInfo_;
    ret = audioDecoder_->Config(sampleInfo_, audioDecContext_);
    CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, ret, "Audio Decoder config failed");

    // 不再创建音频渲染器
    builder_ = nullptr;
    audioRenderer_ = nullptr;

    return AVCODEC_SAMPLE_ERR_OK;
}

int32_t Decode::Init(SampleInfo &sampleInfo) {
    std::unique_lock<std::mutex> lock(mutex_);
    CHECK_AND_RETURN_RET_LOG(!isStarted_, AVCODEC_SAMPLE_ERR_ERROR, "Already started.");
    CHECK_AND_RETURN_RET_LOG(demuxer_ == nullptr && audioDecoder_ == nullptr, AVCODEC_SAMPLE_ERR_ERROR,
                             "Already started.");

    sampleInfo_ = sampleInfo;

    // 只创建音频解码器和分离器
    audioDecoder_ = std::make_unique<AudioDecoder>();
    demuxer_ = std::make_unique<Demuxer>();
    isReleased_ = false;

    int32_t ret = demuxer_->Create(sampleInfo_);
    if (ret != AVCODEC_SAMPLE_ERR_OK) {
        AVCODEC_SAMPLE_LOGE("Create demuxer failed");
        lock.unlock();
        StartRelease();
        return ret;
    }

    ret = CreateAudioDecoder();
    if (ret != AVCODEC_SAMPLE_ERR_OK) {
        AVCODEC_SAMPLE_LOGE("Create audio decoder failed");
        lock.unlock();
        StartRelease();
        return ret;
    }

    AVCODEC_SAMPLE_LOGI("Init succeed");
    return AVCODEC_SAMPLE_ERR_OK;
}

int32_t Decode::Start() {
    std::unique_lock<std::mutex> lock(mutex_);
    int32_t ret;
    CHECK_AND_RETURN_RET_LOG(!isStarted_, AVCODEC_SAMPLE_ERR_ERROR, "Already started.");
    CHECK_AND_RETURN_RET_LOG(demuxer_ != nullptr && audioDecoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR,
                             "Not initialized.");

    // 启动音频解码器
    ret = audioDecoder_->Start();
    if (ret != AVCODEC_SAMPLE_ERR_OK) {
        AVCODEC_SAMPLE_LOGE("Audio Decoder start failed");
        lock.unlock();
        StartRelease();
        return AVCODEC_SAMPLE_ERR_ERROR;
    }

    isStarted_ = true;

    // 创建音频解码输入和输出线程
    audioDecInputThread_ = std::make_unique<std::thread>(&Decode::AudioDecInputThread, this);
    audioDecOutputThread_ = std::make_unique<std::thread>(&Decode::AudioDecOutputThread, this);

    if (audioDecInputThread_ == nullptr || audioDecOutputThread_ == nullptr) {
        AVCODEC_SAMPLE_LOGE("Create thread failed");
        lock.unlock();
        StartRelease();
        return AVCODEC_SAMPLE_ERR_ERROR;
    }

    AVCODEC_SAMPLE_LOGI("Start succeed");
    doneCond_.notify_all();
    return AVCODEC_SAMPLE_ERR_OK;
}

void Decode::StartRelease() {
    AVCODEC_SAMPLE_LOGI("start release");
    std::unique_lock<std::mutex> lock(doneMutex);
    // 如果已经在释放过程中，直接返回
    if (isReleased_) {
        return;
    }
    
    // 标记解码结束和释放状态
    isAudioDone_ = true;
    isReleased_ = true;
    isStarted_ = false; // 确保线程能够正确退出
    
    // 通知所有线程
    doneCond_.notify_all();
    
    // 解锁后再join线程，避免死锁
    if (lock.owns_lock()) {
        lock.unlock();
    }
    
    // 释放线程资源
    if (audioDecInputThread_ && audioDecInputThread_->joinable()) {
        audioDecInputThread_->join();
        audioDecInputThread_.reset(); // 确保不会重复join
    }
    if (audioDecOutputThread_ && audioDecOutputThread_->joinable()) {
        audioDecOutputThread_->join();
        audioDecOutputThread_.reset(); // 确保不会重复join
    }
    
    // 手动释放其他资源，而不是调用Release方法避免重复释放
    std::lock_guard<std::mutex> releaseLock(mutex_);
    if (demuxer_ != nullptr) {
        demuxer_->Release();
        demuxer_.reset();
    }
    
    if (audioDecoder_ != nullptr) {
        audioDecoder_->Release();
        audioDecoder_.reset();
    }
    
    if (audioDecContext_ != nullptr) {
        delete audioDecContext_;
        audioDecContext_ = nullptr;
    }
    
    builder_ = nullptr;
    audioRenderer_ = nullptr;
    
    // 触发完成回调
    if (sampleInfo_.playDoneCallback != nullptr) {
        sampleInfo_.playDoneCallback(sampleInfo_.playDoneCallbackData);
    }
    
    AVCODEC_SAMPLE_LOGI("StartRelease succeed");
}

void Decode::ReleaseThread() {
    if (audioDecInputThread_ && audioDecInputThread_->joinable()) {
        audioDecInputThread_->detach();
        audioDecInputThread_.reset();
    }
    if (audioDecOutputThread_ && audioDecOutputThread_->joinable()) {
        audioDecOutputThread_->detach();
        audioDecOutputThread_.reset();
    }
}

void Decode::Release() {
    std::lock_guard<std::mutex> lock(mutex_);
    isStarted_ = false;

    // 不再需要清理renderQueue，因为我们不使用它

    ReleaseThread();

    if (demuxer_ != nullptr) {
        demuxer_->Release();
        demuxer_.reset();
    }

    if (audioDecoder_ != nullptr) {
        audioDecoder_->Release();
        audioDecoder_.reset();
    }

    if (audioDecContext_ != nullptr) {
        delete audioDecContext_;
        audioDecContext_ = nullptr;
    }

    // 不再需要销毁builder_，因为我们没有创建它
    builder_ = nullptr;
    audioRenderer_ = nullptr;

    doneCond_.notify_all();

    // 触发完成回调
    if (sampleInfo_.playDoneCallback != nullptr) {
        sampleInfo_.playDoneCallback(sampleInfo_.playDoneCallbackData);
    }

    AVCODEC_SAMPLE_LOGI("Release succeed");
}

void Decode::AudioDecInputThread() {
    while (true) {
        CHECK_AND_BREAK_LOG(isStarted_, "Audio decoder input thread out");
        std::unique_lock<std::mutex> lock(audioDecContext_->inputMutex);

        bool condRet = audioDecContext_->inputCond.wait_for(
            lock, 5s, [this]() { return !isStarted_ || !audioDecContext_->inputBufferInfoQueue.empty(); });

        CHECK_AND_BREAK_LOG(isStarted_, "Work done, thread out");
        CHECK_AND_CONTINUE_LOG(!audioDecContext_->inputBufferInfoQueue.empty(),
                               "Buffer queue is empty, continue, cond ret: %{public}d", condRet);

        CodecBufferInfo bufferInfo = audioDecContext_->inputBufferInfoQueue.front();
        audioDecContext_->inputBufferInfoQueue.pop();
        audioDecContext_->inputFrameCount++;
        lock.unlock();

        // 读取音频样本数据
        demuxer_->ReadSample(demuxer_->GetAudioTrackId(), reinterpret_cast<OH_AVBuffer *>(bufferInfo.buffer),
                             bufferInfo.attr);

        // 推送输入缓冲区到解码器
        int32_t ret = audioDecoder_->PushInputBuffer(bufferInfo);
        CHECK_AND_BREAK_LOG(ret == AVCODEC_SAMPLE_ERR_OK, "Push data failed, thread out");

        // 检查是否到达文件末尾
        CHECK_AND_BREAK_LOG(!(bufferInfo.attr.flags & AVCODEC_BUFFER_FLAGS_EOS), "Catch EOS, thread out");
    }
}

void Decode::AudioDecOutputThread() {
    while (true) {
        CHECK_AND_BREAK_LOG(isStarted_, "Audio decoder output thread out");
        std::unique_lock<std::mutex> lock(audioDecContext_->outputMutex);

        bool condRet = audioDecContext_->outputCond.wait_for(
            lock, 5s, [this]() { return !isStarted_ || !audioDecContext_->outputBufferInfoQueue.empty(); });

        CHECK_AND_BREAK_LOG(isStarted_, "Audio decoder output thread out");
        CHECK_AND_CONTINUE_LOG(!audioDecContext_->outputBufferInfoQueue.empty(),
                               "Buffer queue is empty, continue, cond ret: %{public}d", condRet);

        CodecBufferInfo bufferInfo = audioDecContext_->outputBufferInfoQueue.front();
        audioDecContext_->outputBufferInfoQueue.pop();

        // 检查是否到达文件末尾
        bool isEos = (bufferInfo.attr.flags & AVCODEC_BUFFER_FLAGS_EOS) != 0;
        if (isEos) {
            AVCODEC_SAMPLE_LOGI("Catch EOS, thread out");
            // 释放当前缓冲区
            if (audioDecoder_ != nullptr) {
                audioDecoder_->FreeOutputBuffer(bufferInfo.bufferIndex, false);
            }
            break;
        }

        audioDecContext_->outputFrameCount++;
        AVCODEC_SAMPLE_LOGW("Out buffer count: %{public}u, size: %{public}d, offset: %{public}u, flag: %{public}u, "
                            "pts: %{public}" PRId64,
                            audioDecContext_->outputFrameCount, bufferInfo.attr.size, bufferInfo.attr.offset,
                            bufferInfo.attr.flags, bufferInfo.attr.pts);

        // 获取解码后的PCM数据
        uint8_t *source = OH_AVBuffer_GetAddr(reinterpret_cast<OH_AVBuffer *>(bufferInfo.buffer));


        lock.unlock();

        // 直接处理当前缓冲区数据
        if (source != nullptr && bufferInfo.attr.size > 0) {
            // 将PCM数据添加到renderQueue
            std::unique_lock<std::mutex> lockRender(audioDecContext_->renderMutex);
            for (size_t i = 0; i < bufferInfo.attr.size; ++i) {
                audioDecContext_->renderQueue.push(source[i]);
            }
            lockRender.unlock();

            // 将PCM数据传递到ETS层
            DecodeCallbackContext *context = nullptr;
            if (sampleInfo_.playDoneCallbackData != nullptr) {
                context = static_cast<DecodeCallbackContext *>(sampleInfo_.playDoneCallbackData);
                if (context != nullptr) {
                    // 清空之前的数据，确保只传递当前缓冲区数据
                    DecodeCallbackContext *decodeContext = new DecodeCallbackContext;
                    decodeContext->env = context->env;
                    decodeContext->callbackRef = context->callbackRef;

                    decodeContext->audioData.resize(bufferInfo.attr.size);
                    memcpy(decodeContext->audioData.data(), source, bufferInfo.attr.size);

                    // 调用回调函数，将数据传递到ETS层
                    if (sampleInfo_.playDoneCallback != nullptr) {
                        AVCODEC_SAMPLE_LOGI("Sending PCM data to ETS layer, size: %{public}zu", bufferInfo.attr.size);
                        sampleInfo_.playDoneCallback(decodeContext);
                    }
                }
            }
        }

        // 释放输出缓冲区
        if (audioDecoder_ != nullptr) {
            int32_t ret = audioDecoder_->FreeOutputBuffer(bufferInfo.bufferIndex, false);
            if (ret != AVCODEC_SAMPLE_ERR_OK) {
                AVCODEC_SAMPLE_LOGE("Free output buffer failed, thread out");
                break;
            }
        }
    }

    // 安全地等待音频渲染队列清空
    if (audioDecContext_ != nullptr) {
        try {
            std::unique_lock<std::mutex> lockRender(audioDecContext_->renderMutex);
            audioDecContext_->renderCond.wait_for(lockRender, 500ms,
                                              [this]() { return audioDecContext_->renderQueue.size() < 1; });
        } catch (const std::exception& e) {
            AVCODEC_SAMPLE_LOGE("Exception while waiting for render queue: %{public}s", e.what());
        }
    }

    AVCODEC_SAMPLE_LOGI("Out buffer end");

    // 标记音频解码完成
    std::unique_lock<std::mutex> lock(doneMutex);
    isAudioDone_ = true;
    lock.unlock();
    doneCond_.notify_all();

    AVCODEC_SAMPLE_LOGI("Audio decoding completed");
    
    // 不再在输出线程中调用StartRelease，避免影响其他实例的解码
    // 让实例在适当的时机通过外部调用StartRelease或析构函数来释放资源
}